package com.diligent.cloud.printer.server.service.impl;

import com.canny.commons.model.Codes;
import com.canny.commons.model.ObjectResult;
import com.canny.commons.model.Result;
import com.diligent.cloud.printer.server.service.PrinterServerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @Description:
 * @Author: xf107397
 * @Date: Create：in 2020-06-20:15:08
 * @Modified By：
 */
@Service
@Slf4j
public class PrinterServerServiceImpl implements PrinterServerService {
    private static final String FILE_TYPE = "pdf";
    private static final String DEFAULT_PRINTER_NAME = "default";
    private static final CharSequence PPD_FILE_TYPE = "ppd";

    @Override
    public ResponseEntity<Result> printFile(MultipartFile file,String printerName) {
        Result result = new ObjectResult();
        if (file == null || file.isEmpty()) {
            result.modifyCode(Codes.fail.getCode(), "请选择上传的文件！");
            return ResponseEntity.ok(result);
        }
        // 获得原始文件名
        String fileName =file.getOriginalFilename() == null ? "" : file.getOriginalFilename();
        // 截取文件类型; 这里可以根据文件类型进行判断
        String fileType = fileName.substring(fileName.lastIndexOf('.'));
        if (!fileType.contains(FILE_TYPE)) {
            result.modifyCode(Codes.fail.getCode(), "文件格式不正确！");
            return ResponseEntity.ok(result);
        }
        if (StringUtils.isBlank(printerName)){
            printerName = DEFAULT_PRINTER_NAME;
        }
        //上传到指定位置，打印。
        // 截取上传的文件名称
//            String newFileName = DigestUtils.md5DigestAsHex(fileName.getBytes());
        // 拼接上传文件位置
        String newFilePath = getSystemBaseAddress(null) + File.separatorChar
                + UUID.randomUUID().toString().replace("-","")
                + fileType;
        String filepath = uploadFile(file,newFilePath);

        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            result.modifyCode(Codes.success.getCode(), "SUCCESS！");
            return ResponseEntity.ok(result);
        }
        List<String> printerNames = showPrinters();
        System.out.println("=============="+printerNames);
//        boolean contains = printerNames.contains(printerName);
//        if(!contains){
//            result.modifyCode(Codes.fail.getCode(), "请先设置指定的打印机！");
//            return ResponseEntity.ok(result);
//        }
//        printUploadFile(printerName,filepath);
//        result.modifyCode(Codes.success.getCode(), "上传成功！");
        return ResponseEntity.ok(result);
    }

    /**
     * 添加打印机
     * @param printerName
     * @param ppdFile
     * @return
     */
    @Override
    public ResponseEntity<Result> addPrinter(String printerName,String printerUrl, MultipartFile ppdFile) {
        Result result = new ObjectResult();
        if (ppdFile == null || ppdFile.isEmpty()) {
            result.modifyCode(Codes.fail.getCode(), "请选择上传的文件！");
            return ResponseEntity.ok(result);
        }
        // 获得原始文件名
        String fileName =ppdFile.getOriginalFilename() == null ? "" : ppdFile.getOriginalFilename();
       // 截取文件类型; 这里可以根据文件类型进行判断
        String fileType = fileName.substring(fileName.lastIndexOf('.'));
        if (!fileType.contains(PPD_FILE_TYPE)) {
            result.modifyCode(Codes.fail.getCode(), "文件格式不正确！");
            return ResponseEntity.ok(result);
        }
        if (StringUtils.isBlank(printerName)){
            result.modifyCode(Codes.fail.getCode(), "打印机名称不能为空！");
            return ResponseEntity.ok(result);
        }
        if (StringUtils.isBlank(printerUrl)){
            result.modifyCode(Codes.fail.getCode(), "打印机链接不能为空！");
            return ResponseEntity.ok(result);
        }
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            result.modifyCode(Codes.success.getCode(), "SUCCESS！");
            return ResponseEntity.ok(result);
        }
        // 拼接上传文件位置
        String newFilePath = getSystemBaseAddress("/ppdFile") + File.separatorChar + fileName;
        String filepath = uploadFile(ppdFile,newFilePath);

        String cmd = String.format("lpadmin -p %s -E -v %s -m %s"
                ,printerName,printerUrl,filepath);
        String outPutString = execCmds(cmd);
        log.info(outPutString);

        return ResponseEntity.ok(result);
    }

    private void printUploadFile(String printerName, String filepath) {
        //选择打印机
        String cmd = String.format("lp -d %s %s",printerName,filepath);
        String outPutString = execCmds(cmd);
        log.info(outPutString);
    }

    /**
     * 显示打印机列表
     */
    private List<String> showPrinters() {
        List<String> printerNames = new ArrayList<>();
        String cmd = "lpstat -p";
        String outPutString = execCmds(cmd);
        for(String line : outPutString.split("\n")){
            if(StringUtils.isNotBlank(line)){
                //切割获取打印机名称。
                String printerName = line.split(" ")[1];
                if(!"unknown".equals(printerName)){
                    printerNames.add(printerName);
                }
            }
        }
        log.info("printer list : " + printerNames.toString());
        return printerNames;
    }

    /**
     * 执行cmd命令
     *
     * @param cmd
     */
    private String execCmds(String cmd) {
        String result = null;
        String[] cmds = {"/bin/sh", "-c", cmd};
        log.info("执行cmds,{}.", cmds);
        Process process;
        try {
            process = Runtime.getRuntime().exec(cmds);
            process.waitFor();
            InputStream in = process.getInputStream();
            BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = read.readLine()) != null) {
                //执行结果加上回车
                sb.append(line).append("\n");
            }
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 上传文件到指定位置
     *
     * @param file
     * @return
     */
    private String uploadFile(MultipartFile file,String filePath) {
        try {

            // 创建文件实例
            File uploadFile = new File(filePath);
            // 判断文件已经存在，则删除该文件
            if (uploadFile.exists()) {
                uploadFile.delete();
            }
            // 利于spring中的FileCopyUtils.copy()将文件复制
            FileCopyUtils.copy(file.getBytes(), uploadFile);
            return filePath;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    private String getSystemBaseAddress(String path) {
        String basePath;
        String system = System.getProperties().getProperty("os.name");
        if (system.contains("Windows")) {
            basePath = "D://printerUpload";
        } else {
            basePath = "/home/printerUpload";
        }
        if(StringUtils.isNotBlank(path)){
            basePath= basePath+path;
        }
        File dir = new File(basePath);
        if (!dir.exists()) {
            dir.mkdirs();//创建目录
            log.info("创建存储上传文件目录。");
        }
        return basePath;
    }
}
